package com.kma.summer2012.client.view.mainPage;

import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent;
import com.kma.summer2012.client.constants.ConstantsHolder;
import com.kma.summer2012.client.constants.ConstantsPresenter;
import com.kma.summer2012.shared.model.UICrumbsDateAndTime;
import com.kma.summer2012.shared.model.UICrumbsRequest;
import com.kma.summer2012.shared.model.UICrumbsUser;
import com.kma.summer2012.shared.model.UICrumbsWorkItem;

import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: EUGENE
 * Date: 2/17/13
 * Time: 6:42 PM
 * To change this template use File | Settings | File Templates.
 */
public class ColumnsFactory {
    public final static String ID = "Id";
    public final static String DATE = "Date";
    public final static String STATE = "State";
    public final static String TYPE_OF_WORK = "Type of work";
    public final static String REQUESTED_TIME_DATE = "Requested time and date";
    public final static String ASSIGNED_TO = "Assigned to";
    public final static String ASSIGNED_DATE_TIME = "Assigned date and time";
    public final static String TIME_REQUIRED = "Time required";

    public final static String[] ENGINEER_COLUMNS = {ID, TYPE_OF_WORK, ASSIGNED_DATE_TIME};//TIME_REQUIRED
    public final static String[] MANAGER_COLUMNS = {ID, STATE, ASSIGNED_TO, ASSIGNED_DATE_TIME, REQUESTED_TIME_DATE, TYPE_OF_WORK};//TIME_REQUIRED
    public final static String[] OPERATOR_COLUMNS = {ID, DATE, STATE, TYPE_OF_WORK, REQUESTED_TIME_DATE};

    public static ColumnsFactory myself = null;
    private ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler;
    public HashMap<String, Integer> widths;

    private ConstantsPresenter c = ConstantsHolder.getConstants();

    public static ColumnsFactory getInstance() {
        if (myself == null) {
            myself = new ColumnsFactory();
        }
        return myself;
    }

    private ColumnsFactory() {
        fillWidths();
    }

    public interface HasName {
        String getName();
    }

    public List<Column> getColumnsByPosition(String position, ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
        this.sortHandler = sortHandler;
        if (position == null) return null;
        if (position.equals(UICrumbsUser.MANAGER_POSITION)) {
            return doGetColumns(MANAGER_COLUMNS);
        }
        if (position.equals(UICrumbsUser.ENGINEER_POSITION)) {
            return doGetColumns(ENGINEER_COLUMNS);
        }
        if (position.equals(UICrumbsUser.OPERATOR_POSITION)) {
            return doGetColumns(OPERATOR_COLUMNS);
        }
        return null;
    }

    private List<Column> doGetColumns(String[] columns) {
        List<Column> result = new ArrayList<Column>();
        for (String column : columns) {
            Column c = getColumn(column);
            result.add(c);
        }
        return result;
    }


    private Column<UICrumbsRequest, String> getColumn(String name) {
        if (name.equals(ID)) {
            return new IdColumn(this.sortHandler);
        } else if (name.equals(DATE)) {
            return new DateColumn(this.sortHandler);
        } else if (name.equals(STATE)) {
            return new StateColumn(this.sortHandler);
        } else if (name.equals(TYPE_OF_WORK)) {
            return new WorkTypeColumn(this.sortHandler);
        } else if (name.equals(REQUESTED_TIME_DATE)) {
            return new RequestedTimeColumn(this.sortHandler);
        } else if (name.equals(ASSIGNED_TO)) {
            return new AssignedToColumn(this.sortHandler);
        } else if (name.equals(ASSIGNED_DATE_TIME)) {
            return new AssignedDateTimeColumn(this.sortHandler);
        } else if (name.equals(TIME_REQUIRED)) {
            return new TimeRequiredColumn(this.sortHandler);
        }
        return null;
    }

    private void fillWidths() {
        this.widths = new HashMap<String, Integer>();
        this.widths.put(ID, 60);
        this.widths.put(DATE, 120);
        this.widths.put(STATE, 100);
        this.widths.put(TYPE_OF_WORK, 200);
        this.widths.put(REQUESTED_TIME_DATE, 200);
        this.widths.put(ASSIGNED_TO, 160);
        this.widths.put(ASSIGNED_DATE_TIME, 200);
        this.widths.put(TIME_REQUIRED, 60);
    }

    public Integer getColumnWidth(String name) {
        return this.widths.get(name);
    }

    public Column<UICrumbsRequest, Boolean> getCheckBoxColumn() {
        return new CheckBoxColumn();
    }

    public class IdColumn extends Column<UICrumbsRequest, String> implements HasName {
        public IdColumn(Cell<String> cell) {
            super(cell);
        }

        public IdColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    return o1.getId() - o2.getId();
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            return String.valueOf(object.getId());
        }

        @Override
        public String getName() {
            return ID;
        }
    }

    public class DateColumn extends Column<UICrumbsRequest, String> implements HasName {
        public DateColumn(Cell<String> cell) {
            super(cell);
        }

        public DateColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    return o1.getDateOfCreation().compareTo(o2.getDateOfCreation());
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            return object.getDateOfCreation();
        }

        @Override
        public String getName() {
            return DATE;
        }
    }

    public class StateColumn extends Column<UICrumbsRequest, String> implements HasName {
        public StateColumn(Cell<String> cell) {
            super(cell);
        }

        public StateColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    return o1.getState().compareTo(o2.getState());
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            return object.getState();
        }

        @Override
        public String getName() {
            return STATE;
        }
    }

    public class WorkTypeColumn extends Column<UICrumbsRequest, String> implements HasName {
        public WorkTypeColumn(Cell<String> cell) {
            super(cell);
        }

        public WorkTypeColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    Map<UICrumbsWorkItem, Short> works = o1.getUicrumbsWorkItems();
                    String result1 = "";
                    for (UICrumbsWorkItem item : works.keySet()) {
                        result1 += item.getWorkName();
                    }
                    works = o2.getUicrumbsWorkItems();
                    String result2 = "";
                    for (UICrumbsWorkItem item : works.keySet()) {
                        result2 += item.getWorkName();
                    }
                    return result1.compareTo(result2);
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            Map<UICrumbsWorkItem, Short> works = object.getUicrumbsWorkItems();
            String result = "";
            for (UICrumbsWorkItem item : works.keySet()) {
                result += item.getWorkName() + " x" + works.get(item) + "; \n";
            }
            return result;
        }

        @Override
        public String getName() {
            return TYPE_OF_WORK;
        }
    }

    public class RequestedTimeColumn extends Column<UICrumbsRequest, String> implements HasName {
        public String dateToSortWith = "";

        public RequestedTimeColumn(Cell<String> cell) {
            super(cell);
        }

        public RequestedTimeColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    Set<UICrumbsDateAndTime> dateAndTime = o1.getUicrumbsDateAndTimes();
                    String result1 = "";
                    for (UICrumbsDateAndTime item : dateAndTime) {
                        result1 += String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getDateBegin())) + " " + String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getDateEnd())) + "\n ";
                    }
                    if (dateToSortWith.length() > 0) {
                        if (result1.contains(dateToSortWith)) {
                            return -1;
                        }
                    }
                    dateAndTime = o2.getUicrumbsDateAndTimes();
                    String result2 = "";
                    for (UICrumbsDateAndTime item : dateAndTime) {
                        result2 += String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getDateBegin())) + " " + String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getDateEnd())) + "\n ";
                    }
                    if (dateToSortWith.length() > 0) {
                        if (result2.contains(dateToSortWith)) {
                            return 1;
                        }
                    }
                    return result1.compareTo(result2);
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            Set<UICrumbsDateAndTime> dateAndTime = object.getUicrumbsDateAndTimes();
            String result = "";
            for (UICrumbsDateAndTime item : dateAndTime) {
                result += String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getDateBegin())) + " " + String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getDateEnd())) + "\n ";
            }
            return result;
        }

        @Override
        public String getName() {
            return REQUESTED_TIME_DATE;
        }
    }

    public class AssignedToColumn extends Column<UICrumbsRequest, String> implements HasName {
        public AssignedToColumn(Cell<String> cell) {
            super(cell);
        }

        public AssignedToColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    if (o1.getEngineer() == null) return -1;
                    if (o1.getEngineer().getSurnmNmSecondnm() == null) return -1;
                    if (o2.getEngineer() == null) return -1;
                    if (o2.getEngineer().getSurnmNmSecondnm() == null) return -1;
                    return o1.getEngineer().getSurnmNmSecondnm().compareTo(o2.getEngineer().getSurnmNmSecondnm());
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            String result = "";
            if (object.getEngineer() != null) {
                result = object.getEngineer().getSurnmNmSecondnm();
            }
            return result;
        }

        @Override
        public String getName() {
            return ASSIGNED_TO;
        }
    }

    public class AssignedDateTimeColumn extends Column<UICrumbsRequest, String> implements HasName {
        public String dateToSortWith = "";

        public AssignedDateTimeColumn(Cell<String> cell) {
            super(cell);
        }

        public AssignedDateTimeColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    Set<UICrumbsDateAndTime> dateAndTime = o1.getUicrumbsDateAndTimes();
                    String result1 = "";
                    for (UICrumbsDateAndTime item : dateAndTime) {
                        result1 += String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getAssignedTimeBegin())) + " " + String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getAssignedTimeEnd())) + "\n ";
                    }
                    if (dateToSortWith.length() > 0) {
                        if (result1.contains(dateToSortWith)) {
                            return -1;
                        }
                    }
                    dateAndTime = o2.getUicrumbsDateAndTimes();
                    String result2 = "";
                    for (UICrumbsDateAndTime item : dateAndTime) {
                        result2 += String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getAssignedTimeBegin())) + " " + String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getAssignedTimeEnd())) + "\n ";
                    }
                    if (dateToSortWith.length() > 0) {
                        if (result2.contains(dateToSortWith)) {
                            return 1;
                        }
                    }
                    return result1.compareTo(result2);
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            Set<UICrumbsDateAndTime> dateAndTime = object.getUicrumbsDateAndTimes();
            String result = "";
            for (UICrumbsDateAndTime item : dateAndTime) {
                if ((item.getAssignedTimeEnd() != null) && (item.getAssignedTimeBegin() != null))
                    result += String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getAssignedTimeBegin())) + " " + String.valueOf(DateTimeFormat.getFormat(c.DATE_FORMAT()).format(item.getAssignedTimeEnd())) + "\n ";
            }
            return result;
        }

        @Override
        public String getName() {
            return ASSIGNED_DATE_TIME;
        }
    }

    public class TimeRequiredColumn extends Column<UICrumbsRequest, String> implements HasName {
        public TimeRequiredColumn(Cell<String> cell) {
            super(cell);
        }

        public TimeRequiredColumn(ColumnSortEvent.ListHandler<UICrumbsRequest> sortHandler) {
            super(new TextCell());
            this.setSortable(true);
            sortHandler.setComparator(this, new Comparator<UICrumbsRequest>() {
                @Override
                public int compare(UICrumbsRequest o1, UICrumbsRequest o2) {
                    return o1.getDateOfCreation().compareTo(o2.getDateOfCreation());
                }
            });
        }

        @Override
        public String getValue(UICrumbsRequest object) {
            return "";
        }

        @Override
        public String getName() {
            return TIME_REQUIRED;
        }
    }

    public class CheckBoxColumn extends Column<UICrumbsRequest, Boolean> implements HasName {
        public CheckBoxColumn() {
            super((new CheckboxCell(true, false)));
        }

        public CheckBoxColumn(Cell<Boolean> cell) {
            super(cell);
        }

        @Override
        public Boolean getValue(UICrumbsRequest object) {
            return false;
        }

        @Override
        public String getName() {
            return "";
        }
    }

    ;


}
